package com.ynkbny.web.controller;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ynkbny.domain.Formula;
import com.ynkbny.domain.pojo.DeviceListVO;
import com.ynkbny.domain.pojo.FormulaAddVO;
import com.ynkbny.domain.pojo.FormulaVO;
import com.ynkbny.mapper.DeviceMapper;
import com.ynkbny.service.FormulaService;
import com.ynkbny.util.Res;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;

/**
 * @Author YY
 * @Date 2023/8/1 21:19
 */
@Slf4j
@Api(tags = "公式配置相关接口")
@RestController
@RequestMapping("/formula")
public class FormulaController {

    @Resource
    private FormulaService formulaService;

    @Resource
    private DeviceMapper deviceMapper;


    /**
     * 保存或更新公式
     *
     * @Author YY
     * @param formulaAddVo 实体
     * @return Res.ok(update)
     */
    @ApiOperation("保存或更新公式")
    @PostMapping("/saveOrUpdate")
    public Res<Object> saveOrUpdateFormula(FormulaAddVO formulaAddVo){
        log.info("请求参数：{}",formulaAddVo);
        if (formulaAddVo.getFormulaId().isEmpty() && formulaAddVo.getDeviceIdList().isEmpty()){
            return Res.fail("公式错误");
        }
        Formula formula = new Formula();
        BeanUtils.copyProperties(formulaAddVo,formula);
        boolean update = formulaService.saveOrUpdate(formula);
        log.info("返回值：{}",update);
        return Res.ok(update);
    }

    /**
     * 删除公式
     *
     * @Author YY
     * @param id 公式id
     * @return boolean
     */
    @ApiOperation("删除公式")
    @PostMapping("/delete/{id}")
    public Res<Object> deleteFormula(@PathVariable String id){
        log.info("请求参数：{}",id);
        // 查询要删除的公式
        Formula formula = formulaService.getById(id);
        // 根据公式中的社会信用代码查询所有有引用参数的公式列表
        LambdaQueryWrapper<Formula> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.ne(Formula::getFormulaId,"");
        List<Formula> formulaList = formulaService.list(lambdaQueryWrapper);
        // 遍历公式，判断要删除的公式是否被引用
        for (Formula entity : formulaList) {
            String[] split = entity.getFormulaId().split(",");
            // 判断数组是否包含特定的字符串
            if (Arrays.asList(split).contains(formula.getId().toString())) {
                return Res.fail("该公式被引用，无法删除。被引用的公式：" + entity.getDataCode());
            }
        }
        boolean remove = formulaService.removeById(id);
        log.info("返回值：{}",remove);
        return Res.ok(remove);
    }

    /**
     * 查询采集配置项对应的公式
     *
     * @Author YY
     */
    @ApiOperation("查询采集配置项对应的公式")
    @PostMapping("/select/{enterpriseCode}/{dataCode}")
    public Res<Object> selectFormula(@PathVariable String enterpriseCode,@PathVariable String dataCode){
        log.info("请求参数：{},{}",enterpriseCode,dataCode);

        List<Formula> formulaList = formulaService.selectFormulaList(enterpriseCode);
        List<FormulaVO> formulaVOList = new ArrayList<>();
        for (Formula formula : formulaList) {
            FormulaVO vo = new FormulaVO();
            BeanUtils.copyProperties(formula,vo);
            formulaVOList.add(vo);
        }

        List<DeviceListVO> deviceList = deviceMapper.selectByEnterpriseCode(enterpriseCode);

        Map<String,DeviceListVO> deviceMap = new HashMap<>();
        for (DeviceListVO device : deviceList) {
            deviceMap.put(device.getDeviceId(),device);
        }

        FormulaVO vo = new FormulaVO();
        for (Formula formula : formulaList) {
            if (formula.getDataCode().equals(dataCode)){
                BeanUtils.copyProperties(formula,vo);
                // 构建公式展示树型结构
                FormulaVO formulaVO = buildFormulaTree(formulaVOList, deviceMap, vo);
                log.info("返回值：{}",formulaVO);
                return Res.ok(formulaVO);
            }
        }
        log.info("返回值：还没有配置好的公式");
        return Res.fail("还没有配置好的公式");
    }

    /**
     * 构建公式树型结构
     *
     * @Author YY
     * @param formulaVOList formulaVOList
     * @param deviceMap deviceMap
     * @param formulaVO formulaVO
     * @return FormulaVO
     */
    private FormulaVO buildFormulaTree(List<FormulaVO> formulaVOList,Map<String,DeviceListVO> deviceMap,FormulaVO formulaVO){
        log.info("请求参数：{},{},{}",formulaVOList,deviceMap,formulaVO);

        // 设备
        String deviceIdList = formulaVO.getDeviceIdList();
        String[] deviceIdSplit = deviceIdList.split(",");
        for (String deviceId : deviceIdSplit) {
            formulaVO.getDeviceMap().put(deviceId,deviceMap.remove(deviceId));
        }

        // 判断是否还有被引用的公式
        if (ObjectUtils.isEmpty(formulaVO.getFormulaId())){
            return formulaVO;
        }

        // 被引用的公式
        Map<String,FormulaVO> formulaVOMap = new HashMap<>();
        for (FormulaVO formulaVOTemp : formulaVOList) {
            formulaVOMap.put(formulaVOTemp.getId().toString(),formulaVOTemp);
        }
        String formulaIdListStr = formulaVO.getFormulaId();
        String[] formulaIdSplit = formulaIdListStr.split(",");
        for (String formulaId : formulaIdSplit) {
            formulaVO.getFormulaList().add(formulaVOMap.get(formulaId));
        }

        // 递归
        for (FormulaVO vo : formulaVO.getFormulaList()) {
            buildFormulaTree(formulaVOList, formulaVO.getDeviceMap(), vo);
        }

        log.info("返回值：{}",formulaVO);
        return formulaVO;
    }

    /**
     * 查询公式列表
     *
     * @Author YY
     * @param enterpriseCode 企业统一信用代码
     * @return Res.ok(list)
     */
    @ApiOperation("查询公式列表")
    @PostMapping("/select/a")
    public Res<Object> selectFormulaList(@RequestParam("enterpriseCode") String enterpriseCode){
        log.info("请求参数：{}",enterpriseCode);
        List<Formula> list = formulaService.selectFormulaList(enterpriseCode);
        log.info("返回值：{}",list);
        return Res.ok(list);
    }

    /**
     * 查询设备列表
     *
     * @Author YY
     * @param enterpriseCode 企业统一信用代码
     * @return Res.ok(list)
     */
    @ApiOperation("查询设备列表")
    @PostMapping("/select/b")
    public Res<Object> selectDeviceList(String enterpriseCode){
        log.info("请求参数：{}",enterpriseCode);
        List<DeviceListVO> list = deviceMapper.selectByEnterpriseCode(enterpriseCode);
        JSONArray jsonArray = new JSONArray(list);
        Map<String, JSONArray> groupedDevices = new HashMap<>();

        // 通过区域名称分组
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject device = jsonArray.getJSONObject(i);
            String regionName = device.getStr("regionName");

            JSONArray devicesInRegion = groupedDevices.getOrDefault(regionName, new JSONArray());
            devicesInRegion.put(device);

            groupedDevices.put(regionName, devicesInRegion);
        }

        // 将分组设备转换为所需格式
        JSONArray result = new JSONArray();
        for (Map.Entry<String, JSONArray> entry : groupedDevices.entrySet()) {
            JSONObject region = new JSONObject();
            region.putOnce("device", entry.getValue());
            region.putOnce("region", entry.getKey());
            result.put(region);
        }
        log.info("返回值：{}",result);
        return Res.ok(result);
    }
}
